<?php
/**
 * aheadWorks Co.
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the EULA
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://ecommerce.aheadworks.com/AW-LICENSE-COMMUNITY.txt
 * 
 * =================================================================
 *                 MAGENTO EDITION USAGE NOTICE
 * =================================================================
 * This package designed for Magento COMMUNITY edition
 * aheadWorks does not guarantee correct work of this extension
 * on any other Magento edition except Magento COMMUNITY edition.
 * aheadWorks does not provide extension support in case of
 * incorrect edition usage.
 * =================================================================
 *
 * @category   AW
 * @package    AW_Vidtest
 * @copyright  Copyright (c) 2010-2011 aheadWorks Co. (http://www.aheadworks.com)
 * @license    http://ecommerce.aheadworks.com/AW-LICENSE-COMMUNITY.txt
 */
/**
 * Youtube Api Model
 */
class AW_Vidtest_Model_Api_Youtube extends AW_Vidtest_Model_Api_Abstract
{
    /**
     * Name of Application to Description of upload
     */
    const APP_NAME = 'aheadWorks-Vidtest-YouTubeApi-1.0';

    /**
     * Video Entryes Cache
     * @var array
     */
    protected $_entryCahce = array();

    /**
     * Youtube Api Routre Key
     * @var string
     */
    protected $_apiCode = 'youtube';

    /**
     * Http Client
     * @var Zend_Http_Client
     */
    protected $_httpClient = null;

    /**
     * Youtube Adapter
     * @var Zend_Gdata_YouTube
     */
    protected $_youtube = null;

    /**
     * Class constructor
     */
    protected function _construct()
    {
        parent::_construct();
        $this->setAccessToken(Mage::getStoreConfig('vidtest/youtube/access_token'));
        $this->setDeveloperKey(Mage::getStoreConfig('vidtest/youtube/developer_key'));
    }

    /**
     * Retrives app name
     * @return string
     */
    protected function _getAppName()
    {
        return self::APP_NAME;
    }

    /**
     * Retrives server ansver is parseble
     * @param string $strToCheck
     * @return boolean
     */
    protected function _parsebleGdataAnswer($strToCheck)
    {
        $result = array();
        $answer = explode(" ", $strToCheck);
        foreach ($answer as $value){
            try{
                list($key, $value) = explode("=", $value);
            } catch(Exception $e){
                return false;
            }            
        }
        return true;
    }

    /**
     * Retrives Http Client
     * @return Zend_Http_Client
     */
    protected function _getHttpClient()
    {
        if (!$this->_httpClient){
            $this->_httpClient = Zend_Gdata_AuthSub::getHttpClient($this->getAccessToken());
        }
        return $this->_httpClient;
    }

    /**
     * Retrives
     * @return boolean
     */
    public function isLoggedIn($token = null)
    {
        if ($subtoken = Mage::getStoreConfig('vidtest/youtube/access_token')){
           return $this->_parsebleGdataAnswer(Zend_Gdata_AuthSub::getAuthSubTokenInfo($subtoken));
        }
        return false;
    }

    /**
     * Log out from video service
     * @return boolean
     */
    public function logOut($token = null)
    {
        $subtoken = $token ? $token : Mage::getStoreConfig('vidtest/youtube/access_token');
        return Zend_Gdata_AuthSub::AuthSubRevokeToken($subtoken);
    }
    
    /**
     * Rerives Youtube Adapter
     * @return Zend_Gdata_YouTube
     */
    protected function _getYoutube()
    {
        if (!$this->_youtube){
            $this->_youtube = new Zend_Gdata_YouTube($this->_getHttpClient(), $this->_getAppName(), null, $this->getDeveloperKey());
        }
        return $this->_youtube;         
    }

    /**
     * Upload video to servise throw direct method.
     * Delete temporary file
     * Save Video on Video Service
     *
     * @param Varien_Object $file File on store server
     * @param Varien_Object $videoData Prepared date for service
     * @return boolean
     */
    public function uploadVideo($file, $videoData)
    {
        if (!$this->isLoggedIn()){            
            return false;
        }
       
        $youtube = $this->_getYoutube();
        $videoEntry = new Zend_Gdata_YouTube_VideoEntry();


        $filesource = $youtube->newMediaFileSource($file->getTmpName());
        $filesource->setContentType($file->getType());
        $filesource->setSlug($file->getName());
        
        $videoData->setDeveloperKey($this->getDeveloperKey());

        $videoEntry->setMediaSource($filesource);
        $videoEntry->setVideoTitle($videoData->getTitle());
        $videoEntry->setVideoDescription($videoData->getComment() ? $videoData->getComment() : Mage::helper('vidtest')->__('Uploaded by '.$this->_getAppName()));
        $videoEntry->setVideoCategory('People');

        $uploadUrl = 'http://uploads.gdata.youtube.com/feeds/users/default/uploads';

        try {
            $newEntry = $youtube->insertEntry($videoEntry,
                                         $uploadUrl,
                                         'Zend_Gdata_YouTube_VideoEntry');

            $videoId = $newEntry->getVideoId();

        } catch (Zend_Gdata_App_HttpException $httpException) {
            Mage::helper('vidtest')->addCustomerError($httpException->getRawResponseBody());
            $this->_removeTempFile($file->getTmpName());
            return false;
        } catch (Zend_Gdata_App_Exception $e) {
            Mage::helper('vidtest')->addCustomerError($e->getMessage());
            $this->_removeTempFile($file->getTmpName());
            return false;
        }
        $this->_removeTempFile($file->getTmpName());

        if ($videoId){
            return $this->getVideoData($videoId);
        }
        return false;
    }

    /**
     * Retrives parsed time (mm:ss)
     * @param int|string $seconds Seconds
     * @return string
     */
    protected function _getParsedTime($seconds)
    {
        if ($seconds){
            return (($seconds - $seconds%60)/60).':'.((strlen($seconds%60) > 1) ? $seconds%60 : '0'.$seconds%60 );
        }
        return null;
    }

    /**
     * Retrives video data
     * @param string $apiVideoId
     * @return Varien_Object
     */
    public function getPublicVideoData($apiVideoId)
    {
        if (!$this->isLoggedIn()){
            return new Varien_Object(array('error' => true, 'message' => 'Authentitfication failed'));
        }

        if (isset($this->_entryCahce[$apiVideoId])){
            return $this->_entryCahce[$apiVideoId];
        }

        try {
            $video = new Varien_Object(array('id' => $apiVideoId));

            Varien_Profiler::start('aw::vidtest::youtube::get_video_entry');
            $youtube = $this->_getYoutube();
            $entry = $youtube->getVideoEntry($apiVideoId, null, false);
            Varien_Profiler::start('aw::vidtest::youtube::get_video_entry');

            if (count($thumbnails = $entry->getVideoThumbnails())){
                $thumbnail = isset($thumbnails[0]['url']) ? $thumbnails[0]['url'] : '';
            }

            $video->addData(array(
                'thumbnail_url' => $thumbnail,
//                'video_url' => $this->getVideoUrl($apiVideoId),
                'video_url' => $entry->getFlashPlayerUrl(),
                'views' => $entry->getVideoViewCount() ? $entry->getVideoViewCount() : 0,
                'time' => $this->_getParsedTime($entry->getVideoDuration()),
//                'state' => $entry->getVideoState(),
                'title' => $entry->getVideoTitle(),
                'description' => $entry->getVideoDescription(),

            ));

            # Get state
            $state = null;
            if ($control = $entry->getControl()){
                $state = $control->getState();
            }

            if ($state === null){
                $video->setReady(true);
                return $video;
            } elseif ($state->getName() == 'processing') {
                $video->setProcessing(true);
                return $video;
            } elseif ($state->getName() == 'rejected') {
                $video->setRejected(true);
                return $video;
            } elseif ($state->getName() == 'failed') {
                $video->setFailed(true);
                return $video;
            } elseif ($state->getName() == 'deleted') {
                $video->setDeleted(true);
                return $video;
            }

        } catch (Exception $e) {
            return new Varien_Object(array('error' => true, 'message' => $e->getMessage()));
        }

        return new Varien_Object();
    }

    /**
     * Retrives video data
     * @param string $apiVideoId
     * @return Varien_Object
     */
    public function getVideoData($apiVideoId)
    {
        if (!$this->isLoggedIn()){
            return new Varien_Object(array('error' => true, 'message' => 'Authentitfication failed'));
        }
        
        if (isset($this->_entryCahce[$apiVideoId])){
            return $this->_entryCahce[$apiVideoId];
        }

        try {
            $video = new Varien_Object(array('id' => $apiVideoId));

            Varien_Profiler::start('aw::vidtest::youtube::get_video_entry');
            $youtube = $this->_getYoutube();
            $entry = $youtube->getVideoEntry($apiVideoId, null, true);
            Varien_Profiler::start('aw::vidtest::youtube::get_video_entry');
            
            if (count($thumbnails = $entry->getVideoThumbnails())){
                $thumbnail = isset($thumbnails[0]['url']) ? $thumbnails[0]['url'] : '';
            }
          
            $video->addData(array(
                'thumbnail_url' => $thumbnail,
//                'video_url' => $this->getVideoUrl($apiVideoId),
                'video_url' => $entry->getFlashPlayerUrl(),
                'views' => $entry->getVideoViewCount() ? $entry->getVideoViewCount() : 0,
                'time' => $this->_getParsedTime($entry->getVideoDuration()),
//                'state' => $entry->getVideoState(),
                'title' => $entry->getVideoTitle(),
                'description' => $entry->getVideoDescription(),

            ));

            # Get state
            $state = null;
            if ($control = $entry->getControl()){
                $state = $control->getState();
            }            
            if ($state === null){
                $video->setReady(true);
                return $video;
            } elseif ($state->getName() == 'processing') {
                $video->setProcessing(true);
                return $video;
            } elseif ($state->getName() == 'rejected' ) {
                $video->setRejected(true);
                return $video;                
            } elseif ($state->getName() == 'failed') {
                $video->setFailed(true);
                return $video;
            } elseif ($state->getName() == 'deleted') {
                $video->setDeleted(true);
                return $video;
            } elseif ($state->getName() == 'restricted') {
                $video->setReady(true);
                return $video;
            }

        } catch (Exception $e) {
            return new Varien_Object(array('error' => true, 'message' => $e->getMessage()));
        }

        return new Varien_Object();
    }

    /**
     * Retrives url to video thumbnail
     * @param string $apiVideoId
     * @return string
     */
    public function getThumbnailUrl($apiVideoId)
    {
        if ($this->getVideoData($apiVideoId)){
            return $entry->getVideoState()->getThumbnailUrl();
        }
        return '';
    }

    /**
     * Retrives Url to Video
     * @param string $apiVideoId
     * @return string
     */
    public function getVideoUrl($apiVideoId)
    {
        if ($apiVideoId){
            return 'http://www.youtube.com/watch?v='.$apiVideoId;
        }
        return '';
    }

    /**
     * Retrives View Count of Video
     * @param string $apiVideoId
     * @return int
     */
    public function getViews($apiVideoId)
    {
        if ($entry = $this->getPublicVideoData($apiVideoId)){
            return $entry->getViews();
        }
        return 0;
    }

    /**
     * Retrives time of Video
     * @param string $apiVideoId
     * @return string
     */
    public function getTime($apiVideoId)
    {
        if ($this->getVideoData($apiVideoId)){
            return $entry->getVideoState()->getTime();
        }
        return '0:00';
    }

    /**
     * Delete video on service
     * @param string $apiVideoId
     * @return boolean
     */
    public function deleteVideo($apiVideoId)
    {
        if (!$this->isLoggedIn()){
            return new Varien_Object(array('error' => true, 'message' => 'Authentitfication failed'));
        }
        try {
            $youtube = $this->_getYoutube();
            $entry = $youtube->getVideoEntry($apiVideoId, null, true);
            $youtube->delete($entry);
        } catch (Exception $e) {
            return new Varien_Object(array('error' => true, 'message' => $e->getMessage()));
        }
        return new Varien_Object(array('success' => true));
    }

    /**
     * Retrives Rendered Html Code of Player Zend_Gdata_Youtube
     * Possibility to use options
     * @param
     * @param Varien_Object $options still not work
     * @return string
     */
    public function getRenderedPlayer($url, $options = null)
    {
        //TODO add options to player in api model player renderer

        # Fill array
        function fillArray(&$target, &$opt)
        {
            if (is_array($target) && is_array($opt)){
                foreach ($opt as $ok => $ov){
                    foreach ($target as $tk => &$tv){
                        if ($tk == $ok){
                            $tv = $ov;
                        }
                    }
                }
            }
        }

        $objAttrs = array(
                'height' => '400px',
                'width' => '635px'
            );
        $params = array(
                'movie' => $url,
                'allowFullScreen' => 'true',
                'allowScriptAccess' => 'always'
            );
        $embedAttrs = array(
                'src' => $url,
                'allowFullScreen' => 'true',
                'allowScriptAccess' => 'always',
                'height' => '400px',
                'width' => '635px',
                'type' => 'application/x-shockwave-flash'
            );

        fillArray($objAttrs, $options);
        fillArray($params, $options);
        fillArray($embedAttrs, $options);


        $str = '';
        $str .= '<object ';

        foreach ($objAttrs as $k => $v){
            $str .= $k.'="'.$v.'" ';
        }

        $str .= '>';

        foreach ($params as $k => $v){
            $str .= '<param name="'.$k.'" value="'.$v.'" /> ';
        }

        $str .= '<embed ';

        foreach ($embedAttrs as $k => $v){
            $str .= $k.'="'.$v.'" ';
        }
        $str .= '></embed>';
        $str .= '</object>';
        return $str;
    }

    /**
     * Update video data on service
     * @param string $apiVideoId
     * @param Varien_Object $videoData
     * @param Varien_Object
     */
    public function updateVideo($apiVideoId, $videoData)
    {        
        if (!$this->isLoggedIn()){
            return new Varien_Object(array('error' => true, 'message' => 'Authentitfication failed'));
        }
        try {
            $youtube = $this->_getYoutube();
            $entry = $youtube->getVideoEntry($apiVideoId, null, true);
            $entry->setVideoTitle($videoData->getTitle());
            $entry->setVideoDescription($videoData->getDescription());
            $putUrl = $entry->getEditLink()->getHref();
            $youtube->updateEntry($entry, $putUrl);
            
        } catch (Exception $e) {
            return new Varien_Object(array('error' => true, 'message' => $e->getMessage()));
        }
        return new Varien_Object(array('success' => true));
    }

}
